package controllers;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.google.gson.JsonObject;

//import models.AdvancedSearchTag;
//import models.AdvancedSearchTopic;
import models.Entities;

import models.Idea;
import models.IdeaDeveloper;
import models.Organization;
import models.Tag;
//import models.Topic;
//import controllers.Secure.Security;
import models.Topic;

import play.mvc.Controller;
import play.mvc.With;

@With(Secure.class)
public class AdvancedSearchController extends Controller {
	/**
	 * Renders the advanced search view
	 */
	public static void AdvancedSearchView() {

		render();
	}

	/**
	 * Sends the comma-separated format results to the user's e-mail address
	 * 
	 * @param bodyOfMail
	 *            the search results that are in comma-separated format that
	 *            will be the body of the sent e-mail
	 */
	public static void exportByMail(String bodyOfMail) {
		String username = Security.connected();
		IdeaDeveloper user = (IdeaDeveloper) IdeaDeveloper.find(
				"username like ?", username).first();
		String eMail = user.eMail;
		IdeaDeveloper.sendEMail(eMail, "Search Results", bodyOfMail);
		JsonObject backMessage = new JsonObject();
		backMessage.addProperty("reply", "Your Search Results Have Been Sent");
		renderJSON(backMessage.toString());

	}

	/************************** Methods called from the View **************************/

	/**
	 * Calls the method that returns the list of ideas that matches the user's
	 * specified criteria. Forwards the results in the form of strings to the
	 * advanced search view
	 * 
	 * @param title
	 *            the title of the idea
	 * @param description
	 *            the description of the idea
	 * @param creator
	 *            the creator of the idea
	 * @param numberOfViews
	 *            the number of views of the idea should be greater than or
	 *            equal to this number
	 * @param status
	 *            the status of the idea that the user is searching for whether
	 *            promoted for execution or not
	 * @param tags
	 *            the list of tags associated with the ideas that the user
	 *            wishes to retrieve
	 * @param day
	 *            the day that the required idea was created
	 * @param month
	 *            the month that the required idea was created
	 * @param year
	 *            the year that the required idea was created
	 * @param useDate
	 *            specifies how to use the date that the user provided whether
	 *            to retrieve the date created before it after it or on it or
	 *            not to use it at all
	 * @param sort
	 *            specifies how the results are to be sorted
	 * @param organization
	 *            specifies the organization that the idea being searched for
	 *            lies in
	 */
	public static void advancedSearchIdea(String title, String description,
			String creator, String numberOfViews, String status, String tags,
			String day, String month, String year, String useDate, String sort,
			String organization) {

		String username = Security.connected();
		List<Idea> results = new ArrayList<Idea>();
		List<Idea> temp = new ArrayList<Idea>();
		List<Idea> tempResults = new ArrayList<Idea>();
		temp = advancedSearchIdeaNotExact(title, description, creator,
				numberOfViews, status, tags, day, month, year, useDate, sort);
		for (int i = 0; i < temp.size(); i++) {
			if (BrowseController.getIdeaOrganization(temp.get(i).id).indexOf(
					organization) > 0
					|| BrowseController.getIdeaOrganization(temp.get(i).id)
							.startsWith(organization)) {
				tempResults.add(temp.get(i));
			}
		}
		results = viewIdea(tempResults, username);
		String titles = "";
		String ids = "";
		if (results.size() == 0) {
			titles = "No Results Found";
		} else {
			for (int i = 0; i < results.size(); i++) {
				titles += "&" + results.get(i).title;
				ids += "&" + results.get(i).id;
			}
		}
		JsonObject searchResults = new JsonObject();
		searchResults.addProperty("titles", titles);
		searchResults.addProperty("ids", ids);
		searchResults.addProperty("user", username);
		renderJSON(searchResults.toString());
	}

	/**
	 * Retrieves list of topics that match the users input keywords and forwards
	 * it to the view
	 * 
	 * @param title
	 *            the title of the topic
	 * @param description
	 *            the description of the topic
	 * @param creator
	 *            the creator of the topic
	 * @param numberOfViews
	 *            the number of views of the topic should be greater than or
	 *            equal to this number
	 * @param status
	 *            the status of the topic that the user is searching for whether
	 *            promoted for execution or not
	 * @param tags
	 *            the list of tags associated with the topics that the user
	 *            wishes to retrieve
	 * @param day
	 *            the day that the required topic was created
	 * @param month
	 *            the month that the required topic was created
	 * @param year
	 *            the year that the required topic was created
	 * @param useDate
	 *            specifies how to use the date that the user provided whether
	 *            to retrieve the date created before it after it or on it or
	 *            not to use it at all
	 * @param sort
	 *            specifies how the results are to be sorted
	 * @param organization
	 *            specifies the organization that the topic being searched for
	 *            lies in
	 */
	public static void advancedSearchTopic(String title, String description,
			String creator, String numberOfViews, String status, String tags,
			String day, String month, String year, String useDate, String sort,
			String organization) {
		String username = Security.connected();
		List<Topic> results = new ArrayList<Topic>();
		List<Topic> temp = new ArrayList<Topic>();
		List<Topic> tempResults = new ArrayList<Topic>();
		temp = advancedSearchTopicNotExact(title, description, creator,
				numberOfViews, status, tags, day, month, year, useDate, sort);
		for (int i = 0; i < temp.size(); i++) {
			if (BrowseController.getTopicOrganization(temp.get(i).id).indexOf(
					organization) > 0
					|| BrowseController.getTopicOrganization(temp.get(i).id)
							.startsWith(organization)) {
				tempResults.add(temp.get(i));
			}
		}
		results = viewTopic(tempResults, username);
		String titles = "";
		String ids = "";
		if (results.size() == 0) {
			titles = "No Results Found";
		} else {
			for (int i = 0; i < results.size(); i++) {
				titles += "&" + results.get(i).title;
				ids += "&" + results.get(i).id;
			}
		}
		JsonObject searchResults = new JsonObject();
		searchResults.addProperty("titles", titles);
		searchResults.addProperty("ids", ids);
		renderJSON(searchResults.toString());
	}

	/**
	 * Calls the method that retrieves the list of tags that matches the
	 * criteria that the user enters and forwards the results to the view
	 * 
	 * @param name
	 *            the name of the tag that the user wishes to retrieve
	 * @param relatedItems
	 *            the number of items related to that tag is greater than or
	 *            equal to this number
	 * @param day
	 *            the day the tag was created on
	 * @param month
	 *            the month the tag was created on
	 * @param year
	 *            the year the tag was created on
	 * @param useDate
	 *            specifies how to use the date that the user provided whether
	 *            to retrieve the date created before it after it or on it or
	 *            not to use it at all
	 * @param sort
	 *            specifies how the results should be sorted
	 */

	public static void advancedSearchTag(String name, String relatedItems,
			String day, String month, String year, String useDate, String sort) {
		List<Tag> results = new ArrayList<Tag>();
		String titles = "";
		String ids = "";
		results = advancedSearchFindTagExact(name, day, month, year,
				relatedItems, useDate, sort);
		if (results.size() == 0) {
			titles = "No Results Found";
		} else {
			for (int i = 0; i < results.size(); i++) {

				titles += "&" + results.get(i).name;
				ids += "&" + results.get(i).id;

			}
		}
		JsonObject searchResults = new JsonObject();
		searchResults.addProperty("titles", titles);
		searchResults.addProperty("ids", ids);
		renderJSON(searchResults.toString());

	}

	/**
	 * Calls the method that retrieves the list of entities that matches the
	 * criteria that the user enters and forwards the results to the view
	 * 
	 * @param name
	 *            the name of the entity that is being searched on
	 * @param day
	 *            the day that the entity was created on
	 * @param month
	 *            the month that the entity was created on
	 * @param year
	 *            the year that the entity was created on
	 * @param useDate
	 *            specifies how to use the date that the user provided whether
	 *            to retrieve the date created before it after it or on it or
	 *            not to use it at all
	 * @param numberOfViews
	 *            the number of views of the retrieved entity should be greater
	 *            than or equal to this number
	 * @param organization
	 *            the organization that the entity lies in
	 * @param numberOfMembers
	 *            the number of members of the retrieved entity should be
	 *            greater than or equal to this number
	 * @param numberOfTopics
	 *            the number of topics of the retrieved entity should be greater
	 *            than or equal to this number
	 * @param sort
	 *            specifies how the results should be sorted
	 */
	public static void advancedSearchEntity(String name, String day,
			String month, String year, String useDate, String numberOfViews,
			String organization, String numberOfMembers, String numberOfTopics,
			String sort) {
		String username = Security.connected();
		List<Entities> results = new ArrayList<Entities>();
		List<Entities> temp = new ArrayList<Entities>();
		temp = advancedSearchEntityNotExact(name, day, month, year, useDate,
				numberOfViews, organization, numberOfMembers, numberOfTopics,
				sort);
		results = viewEntity(temp, username);
		String titles = "";
		String ids = "";
		if (results.size() == 0) {
			titles = "No Results Found";
		} else {
			for (int i = 0; i < results.size(); i++) {
				titles += "&" + results.get(i).name;
				ids += "&" + results.get(i).id;
			}
		}
		JsonObject searchResults = new JsonObject();
		searchResults.addProperty("titles", titles);
		searchResults.addProperty("ids", ids);
		searchResults.addProperty("user", username);
		renderJSON(searchResults.toString());
	}

	/**
	 * Calls the method that retrieves the list of organizations that matches
	 * the criteria that the user enters and forwards the results to the view
	 * 
	 * @param name
	 *            the name of the organization
	 * @param day
	 *            the day that the organization was created on
	 * @param month
	 *            the month that the organization was created on
	 * @param year
	 *            the year that the organization was created on
	 * @param useDate
	 *            specifies how to use the date that the user provided whether
	 *            to retrieve the date created before it after it or on it or
	 *            not to use it at all
	 * @param numberOfViews
	 *            the number of views of the organization should be greater than
	 *            this number
	 * @param numberOfMembers
	 *            the number of members of the organization should be greater
	 *            than this number
	 * @param numberOfTopics
	 *            the number of topics of the organization should be greater
	 *            than this number
	 * @param sort
	 *            specifies how to sort the search results
	 */
	public static void advancedSearchOrganization(String name, String day,
			String month, String year, String useDate, String numberOfViews,
			String numberOfMembers, String numberOfTopics, String sort) {

		String username = Security.connected();
		List<Organization> results = new ArrayList<Organization>();
		List<Organization> temp = new ArrayList<Organization>();
		temp = advancedSearchOrganizationNotExact(name, day, month, year,
				useDate, numberOfViews, numberOfMembers, numberOfTopics, sort);
		results = viewOrganization(temp, username);
		String titles = "";
		String ids = "";
		if (results.size() == 0) {
			titles = "No Results Found";
		} else {
			for (int i = 0; i < results.size(); i++) {
				titles += "&" + results.get(i).name;
				ids += "&" + results.get(i).name;
			}
		}
		JsonObject searchResults = new JsonObject();
		searchResults.addProperty("titles", titles);
		searchResults.addProperty("ids", ids);
		searchResults.addProperty("user", username);
		renderJSON(searchResults.toString());
	}

	/**
	 * Calls the method that retrieves the list of members that matches the
	 * criteria that the user enters and forwards the results to the view
	 * 
	 * @param fullName
	 *            the full name of the member that the user wishes to search on
	 * @param userName
	 *            the user name of the member that the user wishes to search on
	 * @param eMail
	 *            the e-mail of the member that the user wishes to search on
	 * @param day
	 *            the day that the member was born on
	 * @param month
	 *            the month that the member was born in
	 * @param year
	 *            the year that the member was born in
	 * @param useDate
	 *            specifies how to use the date that the user provided whether
	 *            to retrieve the date created before it after it or on it or
	 *            not to use it at all
	 * @param numberOfIdeas
	 *            the number of ideas that the member contributed should be
	 *            greater than or equal to this number
	 * @param numberOfComments
	 *            the number of comments that the member contributed should be
	 *            greater than or equal to this number
	 * @param sort
	 *            specifies how the results should be sorted
	 */
	public static void advancedSearchMember(String fullName, String userName,
			String eMail, String day, String month, String year,
			String useDate, String numberOfIdeas, String numberOfComments,
			String sort) {
		String user = Security.connected();
		String dateOfBirth = month + "/" + day + "/" + year;
		List<IdeaDeveloper> results = new ArrayList<IdeaDeveloper>();
		List<IdeaDeveloper> temp = new ArrayList<IdeaDeveloper>();
		temp = advancedSearchMemberNotExact(fullName, userName, eMail,
				dateOfBirth, useDate, numberOfIdeas, numberOfComments, sort);
		results = viewMember(temp, user);
		String titles = "";
		String ids = "";
		if (results.size() == 0) {
			titles = "No Results Found";
		} else {
			for (int i = 0; i < results.size(); i++) {
				titles += "&" + results.get(i).username;
				ids += "&" + results.get(i).id;
			}
		}
		JsonObject searchResults = new JsonObject();
		searchResults.addProperty("titles", titles);
		searchResults.addProperty("ids", ids);
		searchResults.addProperty("user", user);
		renderJSON(searchResults.toString());
	}

	/************************** Methods that retrieve from the Database **************************/

	/**
	 * Takes the search keywords. Retrieves from the database a list of ideas
	 * that are the closest possible match to the user's input
	 * 
	 * @param title
	 *            The title of the requested idea
	 * @param description
	 *            The description of the requested idea
	 * @param creator
	 *            The idea's creator
	 * @param numberOfViews
	 *            The number of views of the idea returned is greater than or
	 *            equal to this value
	 * @param status
	 *            The status of the idea whether it is promoted for execution or
	 *            not
	 * @param tags
	 *            The tags associated with this idea
	 * @param day
	 *            The day the idea was created/drafted on
	 * @param month
	 *            The month the idea was created/drafted on
	 * @param year
	 *            The year the idea was created/drafted on
	 * @param dateSearch
	 *            If the search is before or after or exactly the specified date
	 * @param sort
	 *            Specifies how the results that were retrieved from the
	 *            database should be sorted
	 * @return Returns the list of ideas that match the entered keywords
	 */
	public static List<Idea> advancedSearchIdeaNotExact(String title,
			String description, String creator, String numberOfViews,
			String status, String tag, String day, String month, String year,
			String dateSearch, String sort) {
		int intYear = getInt(year) - 1900;
		int intMonth = getInt(month) - 1;
		int intDay = getInt(day);
		Date date = new Date(intYear, intMonth, intDay);
		int numberOfViewsSearch;
		if (numberOfViews.equals("")) {
			numberOfViewsSearch = 0;
		} else {
			numberOfViewsSearch = getInt(numberOfViews);
		}
		boolean state;
		if (status.equals("Promoted for Execution")) {
			state = true;
		} else {
			state = false;
		}
		boolean toSearchTag = !(tag.equals(""));
		String searchDescription = "%" + description + "%";
		String searchTitle = "%" + title + "%";
		String searchCreator = "%" + creator + "%";
		String searchTagName = "%" + tag + "%";
		Tag searchTag = (Tag) Tag.find("name like ?", searchTagName).first();
		List<Idea> list = new ArrayList<Idea>();
		if (sort.equals("sortByViewsAsc")) {
			list = Idea
					.find("title like ? and description like ? and numberOfViews >= ? and promotedForExecution = ? and creator.username like ? order by numberOfViews ASC",
							searchTitle, searchDescription,
							numberOfViewsSearch, state, searchCreator).fetch();
		}
		if (sort.equals("sortByViewsDsc")) {
			list = Idea
					.find("title like ? and description like ? and numberOfViews >= ? and promotedForExecution = ? and creator.username like ? order by numberOfViews DESC",
							searchTitle, searchDescription,
							numberOfViewsSearch, state, searchCreator).fetch();
		}
		if (sort.equals("noSort")) {
			list = Idea
					.find("title like ? and description like ? and numberOfViews >= ? and promotedForExecution = ? and creator.username like ? ",
							searchTitle, searchDescription,
							numberOfViewsSearch, state, searchCreator).fetch();
		}
		if (sort.equals("sortByVotesAsc")) {
			list = Idea
					.find("title like ? and description like ? and numberOfViews >= ? and promotedForExecution = ? and creator.username like ? order by noOfVotes ASC",
							searchTitle, searchDescription,
							numberOfViewsSearch, state, searchCreator).fetch();
		}
		if (sort.equals("sortByVotesDsc")) {
			list = Idea
					.find("title like ? and description like ? and numberOfViews >= ? and promotedForExecution = ? and creator.username like ? order by noOfVotes DESC",
							searchTitle, searchDescription,
							numberOfViewsSearch, state, searchCreator).fetch();
		}

		List<Idea> filtered = new ArrayList<Idea>();
		if (toSearchTag) {
			list = searchTagsNotExactIdea(tag, list);
		}
		if (dateSearch.equals("Exclude Date")) {
			return list;
		}
		if (dateSearch.equals("Include Date")) {
			list = exactDateIdea(date, list);

		}
		if (dateSearch.equals("After this date")) {
			list = afterDateIdea(date, list);

		}
		if (dateSearch.equals("Before this date")) {
			list = beforeDateIdea(date, list);

		}
		return list;

	}

	/**
	 * Takes the search keywords. Retrieves from the database a list of topics
	 * that is the closest possible match to the user's input
	 * 
	 * @param title
	 *            The title of the requested topic
	 * @param description
	 *            The description of the requested topic
	 * @param creator
	 *            The topic's creator
	 * @param numberOfViews
	 *            The number of views of the topic returned is greater than or
	 *            equal to this value
	 * @param status
	 *            The status of the topic whether it is promoted for execution
	 *            or not
	 * @param tags
	 *            The tags associated with this topic
	 * @param day
	 *            The day the topic was created/drafted on
	 * @param month
	 *            The month the topic was created/drafted on
	 * @param year
	 *            The year the topic was created/drafted on
	 * @param dateSearch
	 *            If the search is before or after or exactly the specified date
	 * @return Returns the list of topics that match the entered keywords
	 */
	public static List<Topic> advancedSearchTopicNotExact(String title,
			String description, String creator, String numberOfViews,
			String status, String tag, String day, String month, String year,
			String dateSearch, String sort) {
		int intYear = getInt(year) - 1900;
		int intMonth = getInt(month) - 1;
		int intDay = getInt(day);
		Date date = new Date(intYear, intMonth, intDay);
		int numberOfViewsSearch;
		if (numberOfViews.equals("")) {
			numberOfViewsSearch = 0;
		} else {
			numberOfViewsSearch = getInt(numberOfViews);
		}
		boolean state;
		if (status.equals("Promoted for Execution")) {
			state = true;
		} else {
			state = false;
		}
		boolean toSearchTag = !(tag.equals(""));
		String searchDescription = "%" + description + "%";
		String searchTitle = "%" + title + "%";
		String searchCreator = "%" + creator + "%";
		String searchTagName = "%" + tag + "%";
		List<Topic> list = new ArrayList<Topic>();

		if (sort.equals("noSort")) {
			list = Topic
					.find("title like ? and description like ? and numberOfViews >= ? and promotedForExecution = ? and creator.username like ? ",
							searchTitle, searchDescription,
							numberOfViewsSearch, state, searchCreator).fetch();
		}
		if (sort.equals("sortByRelatedAsc")) {
			list = Topic
					.find("title like ? and description like ? and numberOfViews >= ? and promotedForExecution = ? and creator.username like ? order by numberOfViews ASC",
							searchTitle, searchDescription,
							numberOfViewsSearch, state, searchCreator).fetch();
		}
		if (sort.equals("sortByRelatedDsc")) {
			list = Topic
					.find("title like ? and description like ? and numberOfViews >= ? and promotedForExecution = ? and creator.username like ? order by numberOfViews DESC",
							searchTitle, searchDescription,
							numberOfViewsSearch, state, searchCreator).fetch();
		}
		List<Topic> filtered = new ArrayList<Topic>();
		if (toSearchTag) {
			list = searchTagsNotExactTopic(tag, list);
		}
		if (dateSearch.equals("Exclude Date")) {
			return list;
		}
		if (dateSearch.equals("Include Date")) {
			list = exactDate(date, list);

		}
		if (dateSearch.equals("After this date")) {
			list = afterDateTopic(date, list);

		}
		if (dateSearch.equals("Before this date")) {
			list = beforeDateTopic(date, list);

		}

		return list;

	}

	/**
	 * Takes the search keywords. Retrieves from the database a list of tags
	 * that is the closest possible match to the user's input
	 * 
	 * @param name
	 *            the name of the tag
	 * @param day
	 *            the day that the tag was created on
	 * @param month
	 *            the month that the tag was created on
	 * @param year
	 *            the year that the tag was created on
	 * @param relatedItems
	 *            the number of related items to the tag should be greater than
	 *            or equal to this number
	 * @param dateSearch
	 *            specifies whether to use the date the user chooses and whether
	 *            the date that should be used is exactly the same as, before or
	 *            after the date specified by the user
	 * @param sort
	 *            specifies how the search results should be sorted
	 * @return returns a list of tags that matches the user's search criteria as
	 *         much as possible
	 */
	public static List<Tag> advancedSearchFindTagExact(String name, String day,
			String month, String year, String relatedItems, String dateSearch,
			String sort) {
		int intYear = getInt(year) - 1900;
		int intMonth = getInt(month) - 1;
		int intDay = getInt(day);
		Date date = new Date(intYear, intMonth, intDay);
		int relatedItemsSearch;
		if (relatedItems.equals("")) {
			relatedItemsSearch = 0;
		} else {
			relatedItemsSearch = getInt(relatedItems);
		}

		String searchName = "%" + name + "%";
		List<Tag> list = new ArrayList<Tag>();

		if (sort.equals("noSort")) {
			list = Tag.find("name like ? and relatedItems >= ?", searchName,
					relatedItemsSearch).fetch();
		}

		if (sort.equals("sortByRelatedAsc")) {
			list = Tag
					.find("name like ? and relatedItems >= ? order by relatedItems ASC ",
							searchName, relatedItemsSearch).fetch();
		}
		if (sort.equals("sortByRelatedDsc")) {
			list = Tag
					.find("name like ? and relatedItems >= ? order by relatedItems DESC ",
							searchName, relatedItemsSearch).fetch();
		}

		if (dateSearch.equals("Exclude Date")) {
			return list;
		}
		if (dateSearch.equals("Include Date")) {
			list = exactDateTag(date, list);

		}
		if (dateSearch.equals("After this date")) {
			list = afterDateTag(date, list);

		}
		if (dateSearch.equals("Before this date")) {
			list = beforeDateTag(date, list);

		}

		return list;
	}

	/**
	 * Takes the search keywords. Retrieves from the database a list of entities
	 * that is the closest possible match to the user's input
	 * 
	 * @param name
	 *            the name of the entity
	 * @param day
	 *            the day the entity was created on
	 * @param month
	 *            the month the entity was created on
	 * @param year
	 *            the year the entity was created on
	 * @param useDate
	 *            specifies whether to use the date the user chooses and whether
	 *            the date that should be used is exactly the same as, before or
	 *            after the date specified by the user
	 * @param numberOfViews
	 *            the number of views of the entity should be greater than or
	 *            equal to this number
	 * @param organization
	 *            the organization that the entity lies in
	 * @param numberOfMembers
	 *            the number of members of the entity should be greater than or
	 *            equal to this number
	 * @param numberOfTopics
	 *            the number of topics of the entity should be greater than or
	 *            equal to this number
	 * @param sort
	 *            specifies how the search results are sorted
	 * @return returns a list of entities that matches the user's search
	 *         criteria as much as possible
	 */
	public static List<Entities> advancedSearchEntityNotExact(String name,
			String day, String month, String year, String useDate,
			String numberOfViews, String organization, String numberOfMembers,
			String numberOfTopics, String sort) {
		int intYear = getInt(year) - 1900;
		int intMonth = getInt(month) - 1;
		int intDay = getInt(day);
		Date date = new Date(intYear, intMonth, intDay);
		int numberOfViewsSearch;
		if (numberOfViews.equals("")) {
			numberOfViewsSearch = 0;
		} else {
			numberOfViewsSearch = getInt(numberOfViews);
		}
		int numberOfMembersSearch;
		if (numberOfMembers.equals("")) {
			numberOfMembersSearch = 0;
		} else {
			numberOfMembersSearch = getInt(numberOfMembers);
		}
		int numberOfTopicsSearch;
		if (numberOfTopics.equals("")) {
			numberOfTopicsSearch = 0;
		} else {
			numberOfTopicsSearch = getInt(numberOfTopics);
		}
		String searchName = "%" + name + "%";
		String searchOrganization = "%" + organization + "%";
		List<Entities> list = new ArrayList<Entities>();
		if (sort.equals("noSort")) {
			list = Entities.find("name like ? and liesIn.name like ?",
					searchName, searchOrganization).fetch();
		}
		if (sort.equals("sortByViewsAsc")) {
			list = Entities.find(
					"name like ? and liesIn.name like ? order by views ASC",
					searchName, searchOrganization).fetch();
		}
		if (sort.equals("sortByViewsDsc")) {
			list = Entities.find(
					"name like ? and liesIn.name like ? order by views DESC",
					searchName, searchOrganization).fetch();
		}

		List<Entities> result = new ArrayList<Entities>();
		for (int i = 0; i < list.size(); i++) {
			if (list.get(i).members.size() >= numberOfMembersSearch
					&& list.get(i).topics.size() >= numberOfTopicsSearch
					&& list.get(i).views >= numberOfViewsSearch) {
				result.add(list.get(i));
			}
		}

		if (useDate.equals("Exclude Date")) {
			return result;
		}
		if (useDate.equals("Include Date")) {
			result = exactDateEntity(date, result);
		}
		if (useDate.equals("After this date")) {
			result = afterDateEntity(date, result);

		}
		if (useDate.equals("Before this date")) {
			result = beforeDateEntity(date, result);

		}

		return result;

	}

	/**
	 * Takes the search keywords. Retrieves from the database a list of
	 * organizations that is the closest possible match to the user's input
	 * 
	 * @param name
	 *            the name of the organization
	 * @param day
	 *            the day the organization was created on
	 * @param month
	 *            the month the organization was created on
	 * @param year
	 *            the year the organization was created on
	 * @param useDate
	 *            specifies whether to use the date the user chooses and whether
	 *            the date that should be used is exactly the same as, before or
	 *            after the date specified by the user
	 * @param numberOfViews
	 *            the number of views of the organization should be greater than
	 *            or equal to this number
	 * @param numberOfMembers
	 *            the number of members of the organization should be greater
	 *            than or equal to this number
	 * @param numberOfTopics
	 *            the number of topics of the organization should be greater
	 *            than or equal to this number
	 * @param sort
	 *            specifies how the search results are sorted
	 * @return returns a list of organizations that matches the user's search
	 *         criteria as much as possible
	 */
	public static List<Organization> advancedSearchOrganizationNotExact(
			String name, String day, String month, String year, String useDate,
			String numberOfViews, String numberOfMembers,
			String numberOfTopics, String sort) {
		int intYear = getInt(year) - 1900;
		int intMonth = getInt(month) - 1;
		int intDay = getInt(day);
		Date date = new Date(intYear, intMonth, intDay);
		int numberOfViewsSearch;
		if (numberOfViews.equals("")) {
			numberOfViewsSearch = 0;
		} else {
			numberOfViewsSearch = getInt(numberOfViews);
		}
		int numberOfMembersSearch;
		if (numberOfMembers.equals("")) {
			numberOfMembersSearch = 0;
		} else {
			numberOfMembersSearch = getInt(numberOfMembers);
		}
		int numberOfTopicsSearch;
		if (numberOfTopics.equals("")) {
			numberOfTopicsSearch = 0;
		} else {
			numberOfTopicsSearch = getInt(numberOfTopics);
		}
		String searchName = "%" + name + "%";
		List<Organization> list = new ArrayList<Organization>();
		if (sort.equals("noSort")) {
			list = Organization.find("name like ?", searchName).fetch();
		}
		if (sort.equals("sortByViewsAsc")) {
			list = Organization.find("name like ? order by views ASC",
					searchName).fetch();
		}
		if (sort.equals("sortByViewsDsc")) {
			list = Organization.find("name like ? order by views DESC",
					searchName).fetch();
		}
		List<Organization> result = new ArrayList<Organization>();
		for (int i = 0; i < list.size(); i++) {
			if (list.get(i).members.size() >= numberOfMembersSearch
					&& list.get(i).topics.size() >= numberOfTopicsSearch
					&& list.get(i).views >= numberOfViewsSearch) {
				result.add(list.get(i));
			}
		}
		if (useDate.equals("Exclude Date")) {
			return result;
		}
		if (useDate.equals("Include Date")) {
			result = exactDateOrganization(date, result);
		}
		if (useDate.equals("After this date")) {
			result = afterDateOrganization(date, result);
		}
		if (useDate.equals("Before this date")) {
			result = beforeDateOrganization(date, result);
		}
		return result;
	}

	/**
	 * Takes the search keywords. Retrieves from the database a list of members
	 * that is the closest possible match to the user's input
	 * 
	 * @param fullName
	 *            the full name of the member
	 * @param userName
	 *            the user name of the member
	 * @param eMail
	 *            the e-mail of the member
	 * @param dateOfBirth
	 *            the member's birth date
	 * @param useDate
	 *            specifies whether or not to use the birthday that the user
	 *            chose
	 * @param numberOfIdeas
	 *            the number of ideas that the member has contributed should be
	 *            greater than or equal to this number
	 * @param numberOfComments
	 *            the number of comments that the member has contributed should
	 *            be greater than or equal to this number
	 * @param sort
	 *            determines how the search results will be sorted
	 * @return returns a list of members that matches the user's search criteria
	 *         as much as possible
	 */
	public static List<IdeaDeveloper> advancedSearchMemberNotExact(
			String fullName, String userName, String eMail, String dateOfBirth,
			String useDate, String numberOfIdeas, String numberOfComments,
			String sort) {

		int numberOfIdeasSearch;
		if (numberOfIdeas.equals("")) {
			numberOfIdeasSearch = 0;
		} else {
			numberOfIdeasSearch = getInt(numberOfIdeas);
		}
		int numberOfCommentsSearch;
		if (numberOfComments.equals("")) {
			numberOfCommentsSearch = 0;
		} else {
			numberOfCommentsSearch = getInt(numberOfComments);
		}
		String searchFullName = "%" + fullName + "%";
		String searchUserName = "%" + userName + "%";
		String searchEMail = "%" + eMail + "%";
		String searchBirthDay = "%" + dateOfBirth + "%";
		List<IdeaDeveloper> list = new ArrayList<IdeaDeveloper>();
		if (useDate.equals("Exclude Date")) {
			list = IdeaDeveloper.find(
					"fullName like ? and username like ? and eMail like ? ",
					searchFullName, searchUserName, searchEMail).fetch();
		}

		if (useDate.equals("Include Date")) {
			if (sort.equals("noSort")) {
				list = IdeaDeveloper
						.find("fullName like ? and username like ? and eMail like ? and dateOfBirth like ?",
								searchFullName, searchUserName, searchEMail,
								searchBirthDay).fetch();
			}
			if (sort.equals("sortByPostsAsc")) {
				list = IdeaDeveloper
						.find("fullName like ? and username like ? and eMail like ? and dateOfBirth like ? order by numberOfIdeasPosted ASC",
								searchFullName, searchUserName, searchEMail,
								searchBirthDay).fetch();
			}
			if (sort.equals("sortByPostsDsc")) {
				list = IdeaDeveloper
						.find("fullName like ? and username like ? and eMail like ? and dateOfBirth like ? order by numberOfIdeasPosted DESC",
								searchFullName, searchUserName, searchEMail,
								searchBirthDay).fetch();
			}
			if (sort.equals("sortByCommentsAsc")) {
				list = IdeaDeveloper
						.find("fullName like ? and username like ? and eMail like ? and dateOfBirth like ? order by numberOfComments ASC",
								searchFullName, searchUserName, searchEMail,
								searchBirthDay).fetch();
			}
			if (sort.equals("sortByCommentsDsc")) {
				list = IdeaDeveloper
						.find("fullName like ? and username like ? and eMail like ? and dateOfBirth like ? order by numberOfComments DESC",
								searchFullName, searchUserName, searchEMail,
								searchBirthDay).fetch();
			}
		} else {
			if (sort.equals("noSort")) {
				list = IdeaDeveloper.find(
						"fullName like ? and username like ? and eMail like ?",
						searchFullName, searchUserName, searchEMail).fetch();
			}
			if (sort.equals("sortByPostsAsc")) {
				list = IdeaDeveloper
						.find("fullName like ? and username like ? and eMail like ? order by numberOfIdeasPosted ASC",
								searchFullName, searchUserName, searchEMail)
						.fetch();
			}
			if (sort.equals("sortByPostsDsc")) {
				list = IdeaDeveloper
						.find("fullName like ? and username like ? and eMail like ? order by numberOfIdeasPosted DESC",
								searchFullName, searchUserName, searchEMail)
						.fetch();
			}
			if (sort.equals("sortByCommentsAsc")) {
				list = IdeaDeveloper
						.find("fullName like ? and username like ? and eMail like ? order by numberOfComments ASC",
								searchFullName, searchUserName, searchEMail)
						.fetch();
			}
			if (sort.equals("sortByCommentsDsc")) {
				list = IdeaDeveloper
						.find("fullName like ? and username like ? and eMail like ? order by numberOfComments DESC",
								searchFullName, searchUserName, searchEMail)
						.fetch();
			}

		}
		List<IdeaDeveloper> result = new ArrayList<IdeaDeveloper>();

		for (int i = 0; i < list.size(); i++) {
			if (list.get(i).numberOfIdeasPosted >= numberOfIdeasSearch
					&& list.get(i).numberOfComments >= numberOfCommentsSearch) {
				result.add(list.get(i));
			}
		}
		return result;

	}

	/************************** Helper Methods **************************/

	/**
	 * Returns the integer value of a given string
	 * 
	 * @param string
	 *            the string that should be parsed into an int
	 */
	public static int getInt(String string) {
		return Integer.parseInt(string);
	}

	/**
	 * Retrieves the list of ideas that the user is allowed to see
	 * 
	 * @param list
	 *            the list of ideas that are to be filtered
	 * @param username
	 *            the user name of the user
	 * @return returns the filtered list of ideas that the user may see
	 */
	public static List<Idea> viewIdea(List<Idea> list, String username) {
		List<Idea> result = new ArrayList<Idea>();
		IdeaDeveloper dev = (IdeaDeveloper) IdeaDeveloper.find("username = ?",
				username).first();
		for (int i = 0; i < list.size(); i++) {
			if (dev.canViewIdea(dev, list.get(i))) {
				result.add(list.get(i));
			}

		}
		return result;
	}

	/**
	 * Retrieves the list of topics that the user is allowed to see
	 * 
	 * @param list
	 *            the list of topics that are to be filtered
	 * @param username
	 *            the user name of the user
	 * @return returns the filtered list of topics that the user may see
	 */
	public static List<Topic> viewTopic(List<Topic> list, String username) {
		List<Topic> result = new ArrayList<Topic>();
		IdeaDeveloper dev = (IdeaDeveloper) IdeaDeveloper.find("username = ?",
				username).first();
		for (int i = 0; i < list.size(); i++) {
			if (dev.canViewTopic(dev, list.get(i))) {
				result.add(list.get(i));
			}

		}
		return result;
	}

	/**
	 * Retrieves the list of entities that the user is allowed to see
	 * 
	 * @param list
	 *            the list of entities that are to be filtered
	 * @param username
	 *            the user name of the user
	 * @return returns the filtered list of entities that the user may see
	 */
	public static List<Entities> viewEntity(List<Entities> list, String username) {

		List<Entities> result = new ArrayList<Entities>();
		IdeaDeveloper dev = (IdeaDeveloper) IdeaDeveloper.find("username = ?",
				username).first();
		for (int i = 0; i < list.size(); i++) {
			if (dev.canViewEntity(dev, list.get(i))) {
				result.add(list.get(i));
			}

		}
		return result;
	}

	/**
	 * Retrieves the list of organizations that the user is allowed to see
	 * 
	 * @param list
	 *            the list of organizations that are to be filtered
	 * @param username
	 *            the user name of the user
	 * @return returns the filtered list of organizations that the user may see
	 */
	public static List<Organization> viewOrganization(List<Organization> list,
			String username) {

		List<Organization> result = new ArrayList<Organization>();
		IdeaDeveloper dev = (IdeaDeveloper) IdeaDeveloper.find("username = ?",
				username).first();
		for (int i = 0; i < list.size(); i++) {
			if (dev.canViewOrganization(dev, list.get(i))) {
				result.add(list.get(i));
			}

		}
		return result;
	}

	/**
	 * Retrieves the list of idea developers that the user is allowed to see
	 * 
	 * @param list
	 *            the list of idea developers that are to be filtered
	 * @param username
	 *            the user name of the user
	 * @return returns the filtered list of idea developers that the user may
	 *         see
	 */
	public static List<IdeaDeveloper> viewMember(List<IdeaDeveloper> list,
			String username) {
		List<IdeaDeveloper> result = new ArrayList<IdeaDeveloper>();
		IdeaDeveloper dev = (IdeaDeveloper) IdeaDeveloper.find("username = ?",
				username).first();
		for (int i = 0; i < list.size(); i++) {
			if (dev.canViewProfile(dev, list.get(i))) {
				result.add(list.get(i));
			}

		}
		return result;
	}

	/**
	 * checks if the idea was created after the given date or not
	 * 
	 * @param date
	 *            the date given
	 * @param listOfIdeas
	 *            the list of ideas
	 * @return list of ideas that were created after the given date
	 */
	public static List<Idea> afterDateIdea(Date date, List<Idea> listOfIdeas) {
		List<Idea> temp = new ArrayList<Idea>();
		for (int i = 0; i < listOfIdeas.size(); i++) {
			if (listOfIdeas.get(i).dateOfDraftingPosting.after(date)) {
				temp.add(listOfIdeas.get(i));
			}
		}
		return temp;
	}

	/**
	 * checks if the idea was created before the given date or not
	 * 
	 * @param date
	 *            the date given
	 * @param listOfIdeas
	 *            the list of ideas
	 * @return list of ideas that were created before the given date
	 */
	public static List<Idea> beforeDateIdea(Date date, List<Idea> listOfIdeas) {
		List<Idea> temp = new ArrayList<Idea>();
		for (int i = 0; i < listOfIdeas.size(); i++) {
			if (listOfIdeas.get(i).dateOfDraftingPosting.before(date)) {
				temp.add(listOfIdeas.get(i));
			}
		}
		return temp;
	}

	/**
	 * This method takes a date and a list of ideas and returns all the ideas
	 * whose dates of drafting/posting are exactly the same as the date
	 * specified by the user
	 * 
	 * @param date
	 *            The date that the user specified
	 * @param listOfIdeas
	 *            The list of ideas that should be filtered for the ideas that
	 *            have drafting/posting dates exactly the same as the date
	 *            specified by the user
	 * @return Gets the list of ideas that have drafting/posting dates exactly
	 *         the same as the date specified by the user
	 */
	public static List<Idea> exactDateIdea(Date date, List<Idea> listOfIdeas) {
		List<Idea> result = new ArrayList<Idea>();
		for (int i = 0; i < listOfIdeas.size(); i++) {
			if (listOfIdeas.get(i).dateOfDraftingPosting.getYear() == date
					.getYear()
					&& listOfIdeas.get(i).dateOfDraftingPosting.getMonth() == date
							.getMonth()
					&& listOfIdeas.get(i).dateOfDraftingPosting.getDate() == date
							.getDate()) {
				result.add(listOfIdeas.get(i));
			}
		}
		return result;
	}

	/**
	 * checks if the topic was created after the given date or not
	 * 
	 * @param date
	 *            the date given
	 * @param listOfTopics
	 *            the list of topics
	 * @return list of topics that were created after the given date
	 */
	public static List<Topic> afterDateTopic(Date date, List<Topic> listOfTopics) {
		List<Topic> temp = new ArrayList<Topic>();
		for (int i = 0; i < listOfTopics.size(); i++) {
			if (listOfTopics.get(i).dateOfDraftingPosting.after(date)) {
				temp.add(listOfTopics.get(i));
			}
		}
		return temp;
	}

	/**
	 * checks if the topic was created before the given date or not
	 * 
	 * @param date
	 *            the date given
	 * @param listOfTopics
	 *            the list of topics
	 * @return list of topics that were created before the given date
	 */
	public static List<Topic> beforeDateTopic(Date date,
			List<Topic> listOfTopics) {
		List<Topic> temp = new ArrayList<Topic>();
		for (int i = 0; i < listOfTopics.size(); i++) {
			if (listOfTopics.get(i).dateOfDraftingPosting.before(date)) {
				temp.add(listOfTopics.get(i));
			}
		}
		return temp;
	}

	/**
	 * This method takes a date and a list of topics and returns all the topics
	 * whose dates of drafting/posting are exactly the same as the date
	 * specified by the user
	 * 
	 * @param date
	 *            The date that the user specified
	 * @param listOfTopics
	 *            The list of topics that should be filtered for the topics that
	 *            have drafting/posting dates exactly the same as the date
	 *            specified by the user
	 * @return Gets the list of topics that have drafting/posting dates exactly
	 *         the same as the date specified by the user
	 */
	public static List<Topic> exactDate(Date date, List<Topic> listOfTopics) {
		List<Topic> result = new ArrayList<Topic>();
		for (int i = 0; i < listOfTopics.size(); i++) {
			if (listOfTopics.get(i).dateOfDraftingPosting.getYear() == date
					.getYear()
					&& listOfTopics.get(i).dateOfDraftingPosting.getMonth() == date
							.getMonth()
					&& listOfTopics.get(i).dateOfDraftingPosting.getDate() == date
							.getDate()) {
				result.add(listOfTopics.get(i));
			}
		}
		return result;
	}

	/**
	 * checks if the tag was created after the given date or not
	 * 
	 * @param date
	 *            the date given
	 * @param listOfTags
	 *            the list of tags
	 * @return list of tags that were created after the given date
	 */
	public static List<Tag> afterDateTag(Date date, List<Tag> listOfTags) {
		List<Tag> temp = new ArrayList<Tag>();
		for (int i = 0; i < listOfTags.size(); i++) {
			if (listOfTags.get(i).dateOfCreation.after(date)) {
				temp.add(listOfTags.get(i));
			}
		}
		return temp;
	}

	/**
	 * checks if the tag was created before the given date or not
	 * 
	 * @param date
	 *            the date given
	 * @param listOfTags
	 *            the list of tags
	 * @return list of tags that were created before the given date
	 */
	public static List<Tag> beforeDateTag(Date date, List<Tag> listOfTags) {
		List<Tag> temp = new ArrayList<Tag>();
		for (int i = 0; i < listOfTags.size(); i++) {
			if (listOfTags.get(i).dateOfCreation.before(date)) {
				temp.add(listOfTags.get(i));
			}
		}
		return temp;
	}

	/**
	 * This method gets the list of tags that were created on a given date
	 * 
	 * @param date
	 *            The date that the user enters
	 * @param listOfTags
	 *            The list of tags that are to be filtered
	 * @return Retrieves the list of tags that were created on the given date
	 */
	public static List<Tag> exactDateTag(Date date, List<Tag> listOfTags) {
		List<Tag> temp = new ArrayList<Tag>();
		for (int i = 0; i < listOfTags.size(); i++) {
			if (listOfTags.get(i).dateOfCreation.getYear() == date.getYear()
					&& listOfTags.get(i).dateOfCreation.getMonth() == date
							.getMonth()
					&& listOfTags.get(i).dateOfCreation.getDate() == date
							.getDate()) {
				temp.add(listOfTags.get(i));
			}
		}
		return temp;
	}

	/**
	 * checks if the entity was created after the given date or not
	 * 
	 * @param date
	 *            the date given
	 * @param listOfEntities
	 *            the list of entities
	 * @return list of entities that were created after the given date
	 */
	public static List<Entities> afterDateEntity(Date dateSearch,
			List<Entities> listOfEntities) {
		List<Entities> temp = new ArrayList<Entities>();
		for (int i = 0; i < listOfEntities.size(); i++) {
			if (listOfEntities.get(i).date.after(dateSearch)) {
				temp.add(listOfEntities.get(i));
			}
		}
		return temp;
	}

	/**
	 * checks if the entity was created before the given date or not
	 * 
	 * @param date
	 *            the date given
	 * @param listOfEntities
	 *            the list of entities
	 * @return list of entities that were created before the given date
	 */
	public static List<Entities> beforeDateEntity(Date dateSearch,
			List<Entities> listOfEntities) {
		List<Entities> temp = new ArrayList<Entities>();
		for (int i = 0; i < listOfEntities.size(); i++) {
			if (listOfEntities.get(i).date.before(dateSearch)) {
				temp.add(listOfEntities.get(i));
			}
		}
		return temp;
	}

	/**
	 * This method gets the list of entities that were created on a given date
	 * 
	 * @param date
	 *            The date that the user enters
	 * @param listOfTags
	 *            The list of entities that are to be filtered
	 * @return Retrieves the list of entities that were created on the given
	 *         date
	 */
	public static List<Entities> exactDateEntity(Date date,
			List<Entities> listOfEntities) {
		List<Entities> temp = new ArrayList<Entities>();
		for (int i = 0; i < listOfEntities.size(); i++) {
			if (listOfEntities.get(i).date.getYear() == date.getYear()
					&& listOfEntities.get(i).date.getMonth() == date.getMonth()
					&& listOfEntities.get(i).date.getDate() == date.getDate()) {
				temp.add(listOfEntities.get(i));
			}
		}
		return temp;
	}

	/**
	 * checks if the organization was created after the given date or not
	 * 
	 * @param date
	 *            the date given
	 * @param listOfOrganization
	 *            the list of the entity
	 * @return list of organization that were created after the given date
	 */
	public static List<Organization> afterDateOrganization(Date dateSearch,
			List<Organization> listOfOrganizations) {
		List<Organization> temp = new ArrayList<Organization>();
		for (int i = 0; i < listOfOrganizations.size(); i++) {
			if (listOfOrganizations.get(i).date.after(dateSearch)) {
				temp.add(listOfOrganizations.get(i));
			}
		}
		return temp;
	}

	/**
	 * checks if the organization was created before the given date or not
	 * 
	 * @param date
	 *            the date given
	 * @param listOfOrganization
	 *            the list of the entity
	 * @return list of organization that were created before the given date
	 */
	public static List<Organization> beforeDateOrganization(Date dateSearch,
			List<Organization> listOfOrganizations) {
		List<Organization> temp = new ArrayList<Organization>();
		for (int i = 0; i < listOfOrganizations.size(); i++) {
			if (listOfOrganizations.get(i).date.before(dateSearch)) {
				temp.add(listOfOrganizations.get(i));
			}
		}
		return temp;
	}

	/**
	 * This method gets the list of organizations that were created on a given
	 * date
	 * 
	 * @param date
	 *            The date that the user enters
	 * @param listOfTags
	 *            The list of organizations that are to be filtered
	 * @return Retrieves the list of organizations that were created on the
	 *         given date
	 */
	public static List<Organization> exactDateOrganization(Date date,
			List<Organization> listOfOrganizations) {
		List<Organization> temp = new ArrayList<Organization>();
		for (int i = 0; i < listOfOrganizations.size(); i++) {
			if (listOfOrganizations.get(i).date.getYear() == date.getYear()
					&& listOfOrganizations.get(i).date.getMonth() == date
							.getMonth()
					&& listOfOrganizations.get(i).date.getDate() == date
							.getDate()) {
				temp.add(listOfOrganizations.get(i));
			}
		}
		return temp;
	}

	/**
	 * Gets the list of ideas where each idea is associated with the entered tag
	 * 
	 * @param tag
	 *            The tag that the user wishes to filter his results according
	 *            to
	 * @param listOfIdeas
	 *            The list of ideas that should be filtered for the ideas that
	 *            are associated with the tag
	 * @return The list of ideas where each idea is associated with the tag that
	 *         the user specified
	 */
	public static List<Idea> searchTagsNotExactIdea(String tag,
			List<Idea> listOfIdeas) {
		String searchTag = "%" + tag + "%";
		List<Idea> newList = new ArrayList<Idea>();
		newList = Idea
				.find("select d from Idea as d join d.tags as dd where dd.name like ?",
						searchTag).fetch();
		List<Idea> result = new ArrayList<Idea>();
		for (int i = 0; i < newList.size(); i++) {
			if (listOfIdeas.contains(newList.get(i))) {
				result.add(newList.get(i));
			}
		}
		return result;
	}

	/**
	 * Gets the list of topics where each topic has is associated with the
	 * entered tag
	 * 
	 * @param tag
	 *            The tag that the user wishes to filter his results according
	 *            to
	 * @param listOfTopics
	 *            The list of topics that should be filtered for the topics that
	 *            are associated with the entered tag
	 * @return The list of topics where each topic is associated with the tag
	 *         that the user specified
	 */
	public static List<Topic> searchTagsNotExactTopic(String tag,
			List<Topic> listOfTopics) {
		String searchTag = "%" + tag + "%";
		List<Topic> newList = new ArrayList<Topic>();
		newList = Topic
				.find("select d from Topic as d join d.tags as dd where dd.name like ?",
						searchTag).fetch();
		List<Topic> result = new ArrayList<Topic>();
		for (int i = 0; i < newList.size(); i++) {
			if (listOfTopics.contains(newList.get(i))) {
				result.add(newList.get(i));
			}
		}
		return result;
	}

}
